﻿using AisEncodingLib.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AisEncodingLib
{
	public class EncodeType
	{
		public static string EncodeType1Through3(AisMessageType1Through3 aisMessageType1Through3)
		{
			StringBuilder bits = new StringBuilder();
			bits.Append(Convert.ToString(aisMessageType1Through3.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append(Convert.ToString(aisMessageType1Through3.RepeatIndicator, 2).PadLeft(2, '0')); // 转发指示符
			bits.Append(Convert.ToString(aisMessageType1Through3.Mmsi, 2).PadLeft(30, '0'));
			bits.Append(Convert.ToString((int)aisMessageType1Through3.NavigationStatus, toBase: 2).PadLeft(4, '0')); // 导航状态
			bits.Append(Convert.ToString(aisMessageType1Through3.RateOfTurn, 2).PadLeft(8, '0')); // 旋转速率
			bits.Append(Convert.ToString((int)(aisMessageType1Through3.SpeedOverGround * 10), 2).PadLeft(10, '0')); // 地面航速
			bits.Append(aisMessageType1Through3.PositionAccuracy ? "1" :"0" ); // 位置准确度
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType1Through3.Longitude * 600000), 2).PadLeft(28, '0'));
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType1Through3.Latitude * 600000), 2).PadLeft(27, '0'));
			bits.Append(Convert.ToString((int)(aisMessageType1Through3.CourseOverGround * 10), 2).PadLeft(12, '0')); // 地面航线
			bits.Append(Convert.ToString(aisMessageType1Through3.TrueHeadingDegrees, 2).PadLeft(9, '0'));  // 实际航向
			bits.Append(Convert.ToString(aisMessageType1Through3.TimeStampSecond, 2).PadLeft(6, '0'));   // 时戳
			bits.Append(Convert.ToString((int)aisMessageType1Through3.ManoeuvreIndicator, 2).PadLeft(2, '0'));      // 特定操纵指示符
			bits.Append("000");       // 备用
			bits.Append(aisMessageType1Through3.RaimFlag ? "1" : "0");         // RAIM标志
			bits.Append("0".PadLeft(19, '0'));
			while (bits.Length % 6 != 0) bits.Append('0');
			return AisEncoder.WrapNmea(AisEncoder.Encode6Bit(bits.ToString()));
		}

		public static (string,string) EncodeType5(AisMessageType5 aisMessageType5)
		{
			StringBuilder bits = new StringBuilder();
			bits.Append(Convert.ToString(aisMessageType5.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append(Convert.ToString(aisMessageType5.RepeatIndicator, 2).PadLeft(2, '0')); // 转发指示符
			bits.Append(Convert.ToString(aisMessageType5.Mmsi, 2).PadLeft(30, '0'));
			bits.Append(Convert.ToString(aisMessageType5.AisVersion, 2).PadLeft(2, '0')); // AIS version
			bits.Append(Convert.ToString(aisMessageType5.ImoNumber, 2).PadLeft(30, '0')); // IMO number (simplified)
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType5.CallSign, 7));
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType5.VesselName, 20));
			bits.Append(Convert.ToString((int)aisMessageType5.ShipType, 2).PadLeft(8, '0'));
			bits.Append(Convert.ToString((int)aisMessageType5.DimensionToBow, 2).PadLeft(9, '0'));
			bits.Append(Convert.ToString((int)aisMessageType5.DimensionToStern, 2).PadLeft(9, '0'));
			bits.Append(Convert.ToString((int)aisMessageType5.DimensionToPort, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)aisMessageType5.DimensionToStarboard, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)aisMessageType5.PositionFixType, 2).PadLeft(4, '0'));
			bits.Append(Convert.ToString(aisMessageType5.EtaMonth, 2).PadLeft(4, '0'));
			bits.Append(Convert.ToString(aisMessageType5.EtaDay, 2).PadLeft(5, '0'));
			bits.Append(Convert.ToString(aisMessageType5.EtaHour, 2).PadLeft(5, '0'));
			bits.Append(Convert.ToString(aisMessageType5.EtaMinute, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)(aisMessageType5.Draught10thMetres * 10), 2).PadLeft(8, '0'));
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType5.Destination, 20));
			bits.Append(aisMessageType5.IsDteNotReady ? "0" : "1");
			bits.Append("0");
			int num = 0;
			while (bits.Length % 6 != 0)
			{
                num++;
				bits.Append('0');
			}

			string msg = AisEncoder.Encode6Bit(bits.ToString());
			string msg1 = msg.Substring(0, 48);
            string msg2 = msg.Substring(48);

			msg1 = AisEncoder.WrapNmea("2","1",msg1);
			msg2 = AisEncoder.WrapNmea("2","2", msg2, num);
			return (msg1, msg2);
		}

		public static string EncodeType18(AisMessageType18 aisMessageType18)
		{
			StringBuilder bits = new StringBuilder();
			bits.Append(Convert.ToString(aisMessageType18.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append(Convert.ToString(aisMessageType18.RepeatIndicator, 2).PadLeft(2, '0')); // 转发指示符
			bits.Append(Convert.ToString(aisMessageType18.Mmsi, 2).PadLeft(30, '0'));
			bits.Append("00000000");        // 备用
			bits.Append(Convert.ToString((int)(aisMessageType18.SpeedOverGround * 10), 2).PadLeft(10, '0')); // 地面航速
			bits.Append(aisMessageType18.PositionAccuracy ? "1" : "0"); // 位置准确度
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType18.Longitude * 600000), 2).PadLeft(28, '0'));
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType18.Latitude * 600000), 2).PadLeft(27, '0'));
			bits.Append(Convert.ToString((int)(aisMessageType18.CourseOverGround * 10), 2).PadLeft(12, '0')); // 地面航线
			bits.Append(Convert.ToString(aisMessageType18.TrueHeadingDegrees, 2).PadLeft(9, '0'));		// 实际航向
			bits.Append(Convert.ToString(aisMessageType18.TimeStampSecond, 2).PadLeft(6, '0'));		// 时戳
			bits.Append("00");               // 备用

			bits.Append(Convert.ToString((int)aisMessageType18.CsUnit, 2));       // B类装置标志
			bits.Append(aisMessageType18.HasDisplay ? "1" : "0");                             // B类显示器标志
			bits.Append(aisMessageType18.IsDscAttached ? "1" : "0");                          // B类DSC标志
			bits.Append(aisMessageType18.CanSwitchBands ? "1" : "0");                         // B类带宽标志
			bits.Append(aisMessageType18.CanAcceptMessage22ChannelAssignment ? "1" : "0");    // B类消息22标志
			bits.Append(aisMessageType18.IsAssigned ? "1" : "0");								// 模式标志
			bits.Append(aisMessageType18.RaimFlag ? "1" : "0");								// RAIM标志
			bits.Append(Convert.ToString((int)aisMessageType18.RadioStatusType, 2));  // B类装置标志

			bits.Append("1100000000000000110");                                             // 通信状态
			while (bits.Length % 6 != 0) bits.Append('0');
			return AisEncoder.WrapNmea(AisEncoder.Encode6Bit(bits.ToString()));
		}

		public static (string, string) EncodeType19(AisMessageType19 aisMessageType19)
		{
			StringBuilder bits = new StringBuilder();

			bits.Append(Convert.ToString(aisMessageType19.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append(Convert.ToString(aisMessageType19.RepeatIndicator, 2).PadLeft(2, '0')); // 转发指示符
			bits.Append(Convert.ToString(aisMessageType19.Mmsi, 2).PadLeft(30, '0'));
			bits.Append("00000000");			// 备用
			bits.Append(Convert.ToString((int)(aisMessageType19.SpeedOverGround * 10), 2).PadLeft(10, '0')); // 地面航速
			bits.Append(aisMessageType19.PositionAccuracy ? "1" : "0"); // 位置准确度
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType19.Longitude * 600000), 2).PadLeft(28, '0'));
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType19.Latitude * 600000), 2).PadLeft(27, '0'));
			bits.Append(Convert.ToString((int)(aisMessageType19.CourseOverGround * 10), 2).PadLeft(12, '0')); // 地面航线
			bits.Append(Convert.ToString(aisMessageType19.TrueHeadingDegrees, 2).PadLeft(9, '0'));      // 实际航向
			bits.Append(Convert.ToString(aisMessageType19.TimeStampSecond, 2).PadLeft(6, '0'));     // 时戳
			bits.Append("0000");               // 备用
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType19.ShipName, 20));
			bits.Append(Convert.ToString((int)aisMessageType19.ShipType, 2).PadLeft(8, '0'));
			bits.Append(Convert.ToString((int)aisMessageType19.DimensionToBow, 2).PadLeft(9, '0'));
			bits.Append(Convert.ToString((int)aisMessageType19.DimensionToStern, 2).PadLeft(9, '0'));
			bits.Append(Convert.ToString((int)aisMessageType19.DimensionToPort, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)aisMessageType19.DimensionToStarboard, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)aisMessageType19.PositionFixType, 2).PadLeft(4, '0'));

			bits.Append(aisMessageType19.RaimFlag ? "1" : "0");                             // RAIM标志
			bits.Append(aisMessageType19.IsDteNotReady ? "1" : "0");                        // DTE 数据终端就
			bits.Append(aisMessageType19.IsAssigned ? "1" : "0");							  // 指配模式标志
			bits.Append("0000");            // 备用

			int num = 0;
			while (bits.Length % 6 != 0)
			{
				num++;
				bits.Append('0');
			}

			string msg = AisEncoder.Encode6Bit(bits.ToString());
			string msg1 = msg.Substring(0, 48);
			string msg2 = msg.Substring(48);

			msg1 = AisEncoder.WrapNmea("2", "1", msg1);
			msg2 = AisEncoder.WrapNmea("2", "2", msg2, num);
			return (msg1, msg2);
			//return AisEncoder.WrapNmea(AisEncoder.Encode6Bit(bits.ToString()));
		}

		public static string EncodeType24A(AisMessageType24A aisMessageType24A)
		{
			StringBuilder bits = new StringBuilder();

			bits.Append(Convert.ToString(aisMessageType24A.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append(Convert.ToString(aisMessageType24A.RepeatIndicator, 2).PadLeft(2, '0')); // 转发指示符
			bits.Append(Convert.ToString(aisMessageType24A.Mmsi, 2).PadLeft(30, '0'));
			bits.Append("00"); // 消息部分编号的标识符；对于A部分固定为0
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType24A.ShipName, 20));
			while (bits.Length % 6 != 0) bits.Append('0');
			return AisEncoder.WrapNmea(AisEncoder.Encode6Bit(bits.ToString()));
		}

		public static string EncodeType24B(AisMessageType24B aisMessageType24B)
		{
			StringBuilder bits = new StringBuilder();
			bits.Append(Convert.ToString(aisMessageType24B.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append(Convert.ToString(aisMessageType24B.RepeatIndicator, 2).PadLeft(2, '0')); // 转发指示符
			bits.Append(Convert.ToString(aisMessageType24B.Mmsi, 2).PadLeft(30, '0'));
			bits.Append("01"); // Part B
			bits.Append(Convert.ToString((int)aisMessageType24B.ShipType, 2).PadLeft(8, '0'));
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType24B.MothershipMmsi, 7));
			bits.Append(AisEncoder.EncodeString6bit(aisMessageType24B.CallSign, 7));
			bits.Append(Convert.ToString((int)aisMessageType24B.DimensionToBow, 2).PadLeft(9, '0'));
			bits.Append(Convert.ToString((int)aisMessageType24B.DimensionToStern, 2).PadLeft(9, '0'));
			bits.Append(Convert.ToString((int)aisMessageType24B.DimensionToPort, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)aisMessageType24B.DimensionToStarboard, 2).PadLeft(6, '0'));
			bits.Append(Convert.ToString((int)aisMessageType24B.PositionFixType, 2).PadLeft(4, '0'));
			bits.Append("00");

			while (bits.Length % 6 != 0) bits.Append('0');
			return AisEncoder.WrapNmea(AisEncoder.Encode6Bit(bits.ToString()));
		}

		public static string EncodeType27(AisMessageType27 aisMessageType27)
		{
			StringBuilder bits = new StringBuilder();
			bits.Append(Convert.ToString(aisMessageType27.MessageType, 2).PadLeft(6, '0')); // Msg ID
			bits.Append("11"); // 转发指示符 固定为3
			bits.Append(Convert.ToString(aisMessageType27.Mmsi, 2).PadLeft(30, '0'));

			bits.Append(aisMessageType27.PositionAccuracy ? "1" : "0"); // 位置准确度
			bits.Append(aisMessageType27.RaimFlag ? "1" : "0");         // RAIM标志
			bits.Append(Convert.ToString((int)aisMessageType27.NavigationStatus, toBase: 2).PadLeft(4, '0')); // 导航状态
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType27.Longitude * 600), 2).PadLeft(18, '0'));
			bits.Append(Convert.ToString((int)Math.Round(aisMessageType27.Latitude * 600), 2).PadLeft(17, '0'));
			bits.Append(Convert.ToString(aisMessageType27.SpeedOverGround, 2).PadLeft(6, '0')); // 地面航速
			bits.Append(Convert.ToString(aisMessageType27.CourseOverGround, 2).PadLeft(9, '0')); // 地面航速
			bits.Append(aisMessageType27.GnssPositionStatus ? "1" : "0");         // 位置等待时间
			bits.Append("0");														// 备用

			while (bits.Length % 6 != 0) bits.Append('0');
			return AisEncoder.WrapNmea(AisEncoder.Encode6Bit(bits.ToString()));
		}
	}
}
